﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.SessionState;
using DataTable=System.Data.DataTable;

using ADEVSO.Util;
using SmartParking.Data;
using SmartParking.Data.Entities;
using System.ComponentModel.DataAnnotations;

namespace SmartParking.Bussiness
{
    public class Schedule
    {
        [Display(Name = "Fecha")]
        public DateTime Date { get; private set; }

        public List<ScheduleItem> Items { get; private set; }

        private HttpApplicationState _Application;

        public Schedule(HttpApplicationState application, int parkingZoneID, DateTime date)
        {
            Date = date.Date;
            _Application = application;
            Refresh(parkingZoneID, Date);
        }

        public void Refresh(int parkingZoneID)
        {
            Refresh(parkingZoneID, Date);
        }

        public void Refresh(int parkingZoneID, DateTime date)
        {
            Date = date;

            var reservations = ReservationsManager.GetAllParkingZoneReservations(_Application, parkingZoneID, Date);

            var parkingZone = ParkingManager.GetParkingZone(parkingZoneID);

            FillItems(reservations, parkingZone);
        }

        private void FillItems(List<OrderDetail> reservations, ParkingZone parkingZone)
        {
            Items = new List<ScheduleItem>();
            var start = Convert.ToInt32(parkingZone.OpenHour);
            var end = Convert.ToInt32(parkingZone.CloseHour);
            var regularSpaces = parkingZone.RegularSpaces;
            var spacesToReserve = parkingZone.SpacesToReserve;
            var parkZoneCapacity = regularSpaces;
            for (int i = start; i <= end; i++)
            {
                if (!parkingZone.AllowHalfHour && (i % 2 == 0)) continue;

                var hourReservations = HourReservations(reservations, (Hour)i);
                var hourInUse = HourInUse(reservations, (Hour)i);
                var dayInUse = DayRegularReservations(hourInUse, Date).Count;
                var dayReservations = DayWebReservations(hourReservations, Date).Count;
                Items.Add(new ScheduleItem()
                    {
                        Time = ((Hour)i).ToStringHour(),
                        Availables = regularSpaces - dayInUse,
                        InUse = dayInUse,
                        Reserved = dayReservations,
                        Reservables = spacesToReserve - dayReservations,
                        CssStyle = GetCssClass(parkZoneCapacity, dayInUse)
                    });
            }
        }

        private static List<OrderDetail> HourReservations(List<OrderDetail> reservations, Hour hour)
        {
            var hourReservations =
                from reservation in reservations
                //where (hour.ToDateTime() <= Convert.ToDateTime(reservation.StartDateTime.ToString("hh:mm tt"))
                //&& Convert.ToDateTime(reservation.StartDateTime.ToString("hh:mm tt")) < hour.Add(1).ToDateTime())
                //|| (Convert.ToDateTime(reservation.StartDateTime.ToString("hh:mm tt")) < hour.ToDateTime()
                //&& hour.ToDateTime() < Convert.ToDateTime(reservation.EndDateTime.ToString("hh:mm tt")))
                where (reservation.Order.IsReservation && Convert.ToDateTime(Convert.ToDateTime(reservation.ReservationStartDateTime).ToString("hh:mm tt")) <= hour.ToDateTime() &&
                hour.ToDateTime() < Convert.ToDateTime(Convert.ToDateTime(reservation.ReservationEndDateTime).ToString("hh:mm tt")))
                select reservation;
            return hourReservations.ToList();
        }

        private static List<OrderDetail> HourInUse(List<OrderDetail> reservations, Hour hour)
        {
            var hourInUse =
                from reservation in reservations
                where (!reservation.Order.IsReservation && Convert.ToDateTime(Convert.ToDateTime(reservation.StartDateTime).ToString("hh:mm tt")) <= hour.ToDateTime() &&
                hour.ToDateTime() < Convert.ToDateTime(Convert.ToDateTime(reservation.EndDateTime).ToString("hh:mm tt")))
                select reservation;
            return hourInUse.ToList();
        }

        private static List<OrderDetail> DayRegularReservations(List<OrderDetail> reservations, DateTime day)
        {
            return DayReservations(reservations, day).Where(item => !item.Order.IsReservation).ToList();
        }

        private static List<OrderDetail> DayWebReservations(List<OrderDetail> reservations, DateTime day)
        {
            return DayReservations(reservations, day).Where(item => item.Order.IsReservation).ToList();
        }

        private static List<OrderDetail> DayReservations(List<OrderDetail> reservations, DateTime day)
        {
            return reservations.Where(item => Convert.ToDateTime(item.StartDateTime).ToString("yyyy/MM/dd") == day.ToString("yyyy/MM/dd")).ToList();
        }

        private string GetCssClass(double capacity, double reserved)
        {
            string result = string.Empty;
            double percentage = reserved / capacity * 100;
            if (percentage < 50)
                result = "schedule-LowerThan50";
            else if (percentage > 50 && percentage < 100)
                result = "schedule-GreaterThan50";
            else if (percentage == 100)
                result = "schedule-100";
            else
                result = "schedule-LowerThan50";
            return result;
        }
    }   

    public class ScheduleItem
    {
        [Display(Name = "Hora")]
        public string Time { get; set; }

        [Display(Name = "Disponibles", ShortName = "D")]
        public int Availables { get; set; }

        [Display(Name = "En Uso", ShortName = "U")]
        public int InUse { get; set; }

        [Display(Name = "Reservadas", ShortName = "R")]
        public int Reserved { get; set; }

        [Display(Name = "Reservables", ShortName = "RR")]
        public int Reservables { get; set; }

        public string CssStyle { get; set; }
    }
}
